home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1999 March / EnigmA AMIGA RUN 35 (1999)(G.R. Edizioni)(IT)[!][issue 1999-03].iso / earcd / devel / vbcc-src / machines / alpha / machine.c next >
C/C++ Source or Header  |  1999-01-01  |  59KB  |  1,622 lines

  1. /*  Code generator for a DEC Alpha 64bit RISC cpu with 32       */
  2. /*  general purpose and 32 floating point registers.            */
  3.  
  4. #include "supp.h"
  5.  
  6. static char FILE_[]=__FILE__;
  7.  
  8. /*  Public data that MUST be there.                             */
  9.  
  10. /* Name and copyright. */
  11. char cg_copyright[]="vbcc code-generator for DEC Alpha V0.3b (c) in 1997-99 by Volker Barthelmann";
  12.  
  13. /*  Commandline-flags the code-generator accepts                */
  14. int g_flags[MAXGF]={VALFLAG,VALFLAG,0,0,0,0,0};
  15. char *g_flags_name[MAXGF]={"cpu","fpu","const-in-data","sd","merge-constants","g","no-builtins"};
  16. union ppi g_flags_val[MAXGF];
  17.  
  18. /*  Alignment-requirements for all types in bytes.              */
  19. zlong align[16];
  20.  
  21. /*  Alignment that is sufficient for every object.              */
  22. zlong maxalign;
  23.  
  24. /*  CHAR_BIT for the target machine.                            */
  25. zlong char_bit;
  26.  
  27. /*  Tabelle fuer die Groesse der einzelnen Typen                */
  28. zlong sizetab[16];
  29.  
  30. /*  Minimum and Maximum values each type can have.              */
  31. /*  Must be initialized in init_cg().                           */
  32. zlong t_min[32];
  33. zulong t_max[32];
  34.  
  35. /*  Names of all registers.                                     */
  36. char *regnames[MAXR+1]={"noreg",
  37.                         "$0","$1","$2","$3","$4","$5","$6","$7",
  38.                         "$8","$9","$10","$11","$12","$13","$14","$15",
  39.                         "$16","$17","$18","$19","$20","$21","$22","$23",
  40.                         "$24","$25","$26","$27","$28","$29","$30","$31",
  41.                         "$f0","$f1","$f2","$f3","$f4","$f5","$f6","$f7",
  42.                         "$f8","$f9","$f10","$f11","$f12","$f13","$f14","$f15",
  43.                         "$f16","$f17","$f18","$f19","$f20","$f21","$f22","$f23",
  44.                         "$f24","$f25","$f26","$f27","$f28","$f29","$f30","$f31"};
  45.  
  46. /*  The Size of each register in bytes.                         */
  47. zlong regsize[MAXR+1];
  48.  
  49. /*  A type which can store each register. */
  50. struct Typ *regtype[MAXR+1];
  51.  
  52. /*  regsa[reg]!=0 if a certain register is allocated and should */
  53. /*  not be used by the compiler pass.                           */
  54. int regsa[MAXR+1];
  55.  
  56. /*  Specifies which registers may be scratched by functions.    */
  57. int regscratch[MAXR+1]={0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,
  58.                           1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,1,
  59.                           1,1,0,0,0,0,0,0,0,0,1,1,1,1,1,1,
  60.                           1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
  61.  
  62. struct reg_handle empty_reg_handle={0};
  63.  
  64.  
  65. /****************************************/
  66. /*  Private data and functions.         */
  67. /****************************************/
  68.  
  69. static long malign[16]=  {1,1,2,4,8,4,8,1,8,1,1,1,4,1};
  70. static long msizetab[16]={1,1,2,4,8,4,8,0,8,0,0,0,4,0};
  71.  
  72. static struct Typ ltyp={LONG};
  73.  
  74. static char x_t[16]={'?','b','w','l','q','s','t','?','q'};
  75.  
  76. static int sp=31;                  /*  Stackpointer                        */
  77. static int gp=30;                  /*  Global pointer                      */
  78. static int lr=27;                  /*  Link Register                       */
  79. static int vp=28;                  /*  Virtual frame pointer               */
  80. static int r31=32;                 /*  Read as zero                        */
  81. static int f31=64;                 /*  Read as zero                        */
  82. static int sd=14;                  /*  SmallDataPointer                    */
  83. static int t1=2,t2=3,t3=4;         /*  Temporaries used by code generator  */
  84. static int t4=5,t5=6;
  85. static int f1=34,f2=35,f3=36;      /*  Temporaries used by code generator  */
  86.  
  87. #define DATA 0
  88. #define BSS 1
  89. #define CODE 2
  90.  
  91. static int section=-1,newobj,crsave,helpl,helps,stabs;
  92. static char *codename="\t.text\n",*dataname="\t.data\n",*bssname="";
  93. static int is_const(struct Typ *);
  94. static int balign(struct obj *);
  95. static char *labprefix="$C",*idprefix="";
  96. static long framesize,frameoffset;
  97. static void probj2(FILE *f,struct obj *p,int t);
  98.  
  99. #define ESGN 1
  100. #define EUNS 2
  101. static int st[MAXR+1];
  102.  
  103. static struct fpconstlist {
  104.   struct fpconstlist *next;
  105.   int label,typ;
  106.   union atyps val;
  107. } *firstfpc;
  108.  
  109. static void move_reg(FILE *f,int s,int t)
  110. {
  111.   if(t==r31||t==f31) ierror(0);
  112.   if(s<=32&&t>32) ierror(0);
  113.   if(t<=32&&s>32) ierror(0);
  114.   if(s==t) return;
  115.   if(s<=32){
  116.     fprintf(f,"\tbis\t%s,%s,%s\n",regnames[r31],regnames[s],regnames[t]);
  117.   }else{
  118.     fprintf(f,"\tcpys\t%s,%s,%s\n",regnames[s],regnames[s],regnames[t]);
  119.   }
  120.   st[t]=st[s];
  121. }
  122.  
  123. static int addfpconst(struct obj *o,int t)
  124. {
  125.   struct fpconstlist *p=firstfpc;
  126.   t&=NQ;
  127.   if(g_flags[4]&USEDFLAG){
  128.     for(p=firstfpc;p;p=p->next){
  129.       if(t==p->typ){
  130.         eval_const(&p->val,t);
  131.         if(t==INT&&zleqto(vlong,zi2zl(o->val.vint))) return(p->label);
  132.         if(t==LONG&&zleqto(vlong,o->val.vlong)) return(p->label);
  133.         if(t==FLOAT&&zdeqto(vdouble,zf2zd(o->val.vfloat))) return(p->label);
  134.         if(t==DOUBLE&&zdeqto(vdouble,o->val.vdouble)) return(p->label);
  135.       }
  136.     }
  137.   }
  138.   p=mymalloc(sizeof(struct fpconstlist));
  139.   p->next=firstfpc;
  140.   p->label=++label;
  141.   p->typ=t;
  142.   p->val=o->val;
  143.   firstfpc=p;
  144.   return(p->label);
  145. }
  146.  
  147. #define REG_IND 1
  148. #define IMM_IND 2
  149.  
  150. static struct obj *cam(int flags,int base,int align,long offset)
  151. /*  Initializes an addressing-mode structure and returns a pointer to   */
  152. /*  that object. Will not survive a second call!                        */
  153. {
  154.   static struct obj obj;
  155.   static struct AddressingMode am;
  156.   obj.am=&am;
  157.   am.flags=flags;
  158.   am.base=base;
  159.   am.offset=offset;
  160.   am.align=align;
  161.   return(&obj);
  162. }
  163.  
  164. static char *dct[]={"??","byte","short","long","quad","long","long","quad","??","??","??","??"};
  165.  
  166. static void load_address(FILE *f,int r,struct obj *o,int typ)
  167. /*  Generates code to load the address of a variable into register r.   */
  168. {
  169.   if((o->flags&VAR)&&(o->v->storage_class==AUTO||o->v->storage_class==REGISTER)){
  170.     long of=zl2l(o->v->offset);
  171.     if(of>=0)
  172.       of+=frameoffset+zl2l(o->val.vlong);
  173.     else
  174.       of=-of-zl2l(maxalign)+framesize+zl2l(o->val.vlong);
  175.     if(of>32767) ierror(0);
  176.     fprintf(f,"\tlda\t%s,%ld(%s)\n",regnames[r],of,regnames[sp]);
  177.   }else{
  178.     fprintf(f,"\tlda\t%s,",regnames[r]);
  179.     probj2(f,o,typ);fprintf(f,"\n");
  180.   }
  181.   st[r]=ESGN;
  182. }
  183. static void load_obj(FILE *f,int r,struct obj *o,int typ,int tmp)
  184. {
  185.   int adr,shift,al;
  186.   switch(typ&NQ){
  187.   case POINTER:
  188.   case DOUBLE:
  189.   case FLOAT:
  190.   case LONG:
  191.   case INT:
  192.     fprintf(f,"\tld%c\t%s,",x_t[typ&NQ],regnames[r]);
  193.     probj2(f,o,typ);fprintf(f,"\n");
  194.     st[r]=ESGN;return;
  195.   case SHORT:
  196.     al=balign(o);
  197.     if(al>=0){
  198.       fprintf(f,"\tldq_u\t%s,",regnames[r]);
  199.       probj2(f,o,typ);fprintf(f,"\n");
  200.       shift=64-16-al*8;
  201.       if(shift) fprintf(f,"\tsll\t%s,%d,%s\n",regnames[r],shift,regnames[r]);
  202.       if(typ&UNSIGNED){
  203.         fprintf(f,"\tsrl\t%s,%d,%s\n",regnames[r],64-16,regnames[r]);
  204.         st[r]=EUNS;
  205.       }else{
  206.         fprintf(f,"\tsra\t%s,%d,%s\n",regnames[r],64-16,regnames[r]);
  207.         st[r]=ESGN;
  208.       }
  209.       return;
  210.     }
  211.     adr=0;
  212.     if(o->am&&o->am->offset==0)
  213.       adr=o->am->base;
  214.     else if(zleqto(o->val.vlong,l2zl(0L)))
  215.       adr=o->reg;
  216.     if(!adr){
  217.       adr=tmp;load_address(f,adr,o,POINTER);
  218.     }
  219.  
  220.     if(typ&UNSIGNED){
  221.       fprintf(f,"\tbic\t%s,6,%s\n",regnames[adr],regnames[t4]); /* ldq_u ? */
  222.       fprintf(f,"\tldq\t%s,0(%s)\n",regnames[t5],regnames[t4]);
  223.       fprintf(f,"\tbic\t%s,1,%s\n",regnames[adr],regnames[t4]);
  224.       fprintf(f,"\textwl\t%s,%s,%s\n",regnames[t5],regnames[t4],regnames[r]);
  225.       /*
  226.       fprintf(f,"\tbic\t%s,2,%s\n",regnames[adr],regnames[t4]);
  227.       fprintf(f,"\tand\t%s,2,%s\n",regnames[adr],regnames[t5]);
  228.       fprintf(f,"\tldq\t%s,0(%s)\n",regnames[r],regnames[t4]);
  229.       fprintf(f,"\textwh\t%s,%s,%s\n",regnames[r],regnames[t5],regnames[r]);
  230.       */
  231.       st[r]=EUNS;return;
  232.     }else{
  233.       fprintf(f,"\tbic\t%s,6,%s\n",regnames[adr],regnames[t4]);
  234.       fprintf(f,"\tand\t%s,6,%s\n",regnames[adr],regnames[t5]);
  235.       fprintf(f,"\tldq\t%s,0(%s)\n",regnames[r],regnames[t4]);
  236.       fprintf(f,"\tlda\t%s,2(%s)\n",regnames[t5],regnames[t5]);
  237.       fprintf(f,"\textqh\t%s,%s,%s\n",regnames[r],regnames[t5],regnames[r]);
  238.       fprintf(f,"\tsra\t%s,48,%s\n",regnames[r],regnames[r]);
  239.       st[r]=ESGN;return;
  240.     }
  241.   case CHAR:
  242.     al=balign(o);
  243.     if(al>=0){
  244.       fprintf(f,"\tldq_u\t%s,",regnames[r]);
  245.       probj2(f,o,typ);fprintf(f,"\n");
  246.       shift=64-8-al*8;
  247.       if(shift&&al) fprintf(f,"\tsll\t%s,%d,%s\n",regnames[r],shift,regnames[r]);
  248.       if(typ&UNSIGNED){
  249.         if(al==0)
  250.           fprintf(f,"\tand\t%s,255,%s\n",regnames[r],regnames[r]);
  251.         else
  252.           fprintf(f,"\tsrl\t%s,%d,%s\n",regnames[r],64-8,regnames[r]);
  253.         st[r]=EUNS;
  254.       }else{
  255.         if(al==0)
  256.           fprintf(f,"\tsextb\t%s,%s\n",regnames[r],regnames[r]);
  257.         else
  258.           fprintf(f,"\tsra\t%s,%d,%s\n",regnames[r],64-8,regnames[r]);
  259.         st[r]=ESGN;
  260.       }
  261.       return;
  262.     }
  263.     if(typ&UNSIGNED){
  264.       adr=0;
  265.       if(o->am&&o->am->offset==0)
  266.         adr=o->am->base;
  267.       else if(zleqto(o->val.vlong,l2zl(0L)))
  268.         adr=o->reg;
  269.       if(!adr){
  270.         adr=tmp; load_address(f,adr,o,POINTER);
  271.       }
  272.       fprintf(f,"\tldq_u\t%s,0(%s)\n",regnames[r],regnames[adr]);
  273.       fprintf(f,"\textbl\t%s,%s,%s\n",regnames[r],regnames[adr],regnames[r]);
  274.       st[r]=EUNS;return;
  275.     }else{
  276.       fprintf(f,"\tldq_u\t%s,",regnames[t5]);
  277.       probj2(f,o,typ);fprintf(f,"\n\tlda\t%s,",regnames[t4]);
  278.       if(o->am) o->am->offset++; else o->val.vlong=zladd(o->val.vlong,l2zl(1L));
  279.       probj2(f,o,typ);
  280.       if(o->am) o->am->offset--; else o->val.vlong=zlsub(o->val.vlong,l2zl(1L));
  281.       fprintf(f,"\n\textqh\t%s,%s,%s\n",regnames[t5],regnames[t4],regnames[t5]);
  282.       fprintf(f,"\tsra\t%s,56,%s\n",regnames[t5],regnames[r]);
  283.       st[r]=ESGN;return;
  284.     }
  285.   }
  286.   ierror(0);
  287. }
  288. static void load_reg(FILE *f,int r,struct obj *o,int typ,int tmp)
  289. /*  Generates code to load a memory object into register r. tmp is a    */
  290. /*  general purpose register which may be used. tmp can be r.           */
  291. {
  292.   typ&=NU;
  293.   if(o->am){
  294.     load_obj(f,r,o,typ,tmp);
  295.     return;
  296.   }
  297.   if(o->flags&KONST){
  298.     long l;int lab;
  299.     eval_const(&o->val,typ);
  300.     if(typ==FLOAT||typ==DOUBLE){
  301.       lab=addfpconst(o,typ);
  302.       fprintf(f,"\tlda\t%s,%s%d\n",regnames[tmp],labprefix,lab);
  303.       fprintf(f,"\tld%c\t%s,0(%s)\n",x_t[typ&NQ],regnames[r],regnames[tmp]);
  304.       st[r]=ESGN;
  305.       return;
  306.     }
  307.     if(zlleq(vlong,l2zl(32767))&&zlleq(l2zl(-32768),vlong)){
  308.       fprintf(f,"\tlda\t%s,%ld(%s)\n",regnames[r],zl2l(vlong),regnames[r31]);
  309.     }else{
  310. /*       if((typ&NQ)<INT) ierror(0); */
  311.       lab=addfpconst(o,typ);
  312.       fprintf(f,"\tlda\t%s,%s%d\n",regnames[tmp],labprefix,lab);
  313.       fprintf(f,"\tldq\t%s,0(%s)\n",regnames[r],regnames[tmp]);
  314.     }
  315.     st[r]=ESGN;
  316.     return;
  317.   }
  318.   if((o->flags&VAR)&&(o->v->storage_class==EXTERN||o->v->storage_class==STATIC)){
  319.     if(!(o->flags&VARADR)){
  320.       load_address(f,tmp,o,POINTER);
  321.       load_obj(f,r,cam(IMM_IND,tmp,balign(o),0L),typ,tmp);
  322.     }else{
  323.       load_address(f,r,o,POINTER);
  324.     }
  325.   }else{
  326.     if(o->am||(o->flags&(DREFOBJ|REG))==REG){
  327.       if(r!=o->reg)
  328.         move_reg(f,o->reg,r);
  329.     }else{
  330.       if(o->flags&DREFOBJ) ierror(0);
  331.       load_obj(f,r,o,typ,tmp);
  332.     }
  333.   }
  334. }
  335.  
  336.  
  337. static void store_reg(FILE *f,int r,struct obj *o,int typ)
  338. /*  Generates code to store register r into memory object o.            */
  339. {
  340.   int adr,t6,t7;
  341.   if((o->flags&(REG|DREFOBJ))==REG) ierror(0);
  342.   if(r==t1){ t6=t2;t7=t3;}
  343.   else if(r==t2) {t6=t1;t7=t3;}
  344.   else {t6=t1;t7=t2;}
  345.   if((typ&NQ)>SHORT){
  346.     if((o->flags&VAR)&&(o->v->storage_class==EXTERN||o->v->storage_class==STATIC)){
  347.       load_address(f,t6,o,POINTER);
  348.       fprintf(f,"\tst%c\t%s,0(%s)\n",x_t[typ&NQ],regnames[r],regnames[t6]);
  349.       return;
  350.     }
  351.     fprintf(f,"\tst%c\t%s,",x_t[typ&NQ],regnames[r]);
  352.     probj2(f,o,typ);fprintf(f,"\n");
  353.     return;
  354.   }else{
  355.     adr=0;
  356.     if(o->am&&o->am->offset==0){
  357.       adr=o->am->base;
  358.       if(adr<1||adr>32) ierror(0);
  359.     }else if((o->flags®)&&zleqto(o->val.vlong,l2zl(0L))){
  360.       adr=o->reg;
  361.       if(adr<1||adr>32) ierror(0);
  362.     }
  363.     if(!adr){
  364.       adr=t7; load_address(f,adr,o,POINTER);
  365.     }
  366.     if(adr<1||adr>32) ierror(0);
  367.     if((typ&NQ)==SHORT){
  368.       fprintf(f,"\tbic\t%s,2,%s\n",regnames[adr],regnames[t4]);
  369.       fprintf(f,"\tldl\t%s,0(%s)\n",regnames[t6],regnames[t4]);
  370.       fprintf(f,"\tand\t%s,2,%s\n",regnames[adr],regnames[t5]);
  371.       fprintf(f,"\tmskwl\t%s,%s,%s\n",regnames[t6],regnames[t5],regnames[t6]);
  372.       fprintf(f,"\tinswl\t%s,%s,%s\n",regnames[r],regnames[t5],regnames[t7]);
  373.       fprintf(f,"\tbis\t%s,%s,%s\n",regnames[t6],regnames[t7],regnames[t6]);
  374.       fprintf(f,"\tstl\t%s,0(%s)\n",regnames[t6],regnames[t4]);
  375.       return;
  376.     }else{
  377.       fprintf(f,"\tldq_u\t%s,0(%s)\n",regnames[t4],regnames[adr]);
  378.       fprintf(f,"\tmskbl\t%s,%s,%s\n",regnames[t4],regnames[adr],regnames[t4]);
  379.       fprintf(f,"\tinsbl\t%s,%s,%s\n",regnames[r],regnames[adr],regnames[t5]);
  380.       fprintf(f,"\tbis\t%s,%s,%s\n",regnames[t4],regnames[t5],regnames[t4]);
  381.       fprintf(f,"\tstq_u\t%s,0(%s)\n",regnames[t4],regnames[adr]);
  382.       return;
  383.     }
  384.   }
  385. }
  386.  
  387. static void extend(FILE *f,int r)
  388. {
  389.   if(!r) return;
  390.   if(st[r]==ESGN) return;
  391.   fprintf(f,"\taddl\t%s,%s,%s\n",regnames[r],regnames[r31],regnames[r]);
  392.   st[r]=ESGN;
  393. }
  394. static void uextend(FILE *f,int r)
  395. {
  396.   if(!r) return;
  397.   if(st[r]==EUNS) return;
  398.   fprintf(f,"\tzapnot\t%s,15,%s\n",regnames[r],regnames[r]);
  399.   st[r]=EUNS;
  400. }
  401.  
  402. static struct IC *do_refs(FILE *,struct IC *);
  403. static void pr(FILE *,struct IC *);
  404. static void function_top(FILE *,struct Var *,long,long);
  405. static void function_bottom(FILE *f,struct Var *,long,long);
  406.  
  407. #define isreg(x) ((p->x.flags&(REG|DREFOBJ))==REG)
  408.  
  409. static int q1reg,q2reg,zreg;
  410.  
  411. static char *ccs[]={"eq","ne","lt","ge","le","gt",""};
  412. static char *logicals[]={"bis","xor","and"};
  413. static char *arithmetics[]={"sll","srl","add","sub","mul","div","rem"};
  414.  
  415. static struct IC *do_refs(FILE *f,struct IC *p)
  416. /*  Does some pre-processing like fetching operands from memory to      */
  417. /*  registers etc.                                                      */
  418. {
  419.   int typ=p->typf,typ1,reg,c=p->code;
  420.  
  421.   if(c==CONVCHAR) typ=CHAR;
  422.   if(c==CONVUCHAR) typ=UNSIGNED|CHAR;
  423.   if(c==CONVSHORT) typ=SHORT;
  424.   if(c==CONVUSHORT) typ=UNSIGNED|SHORT;
  425.   if(c==CONVINT) typ=INT;
  426.   if(c==CONVUINT) typ=UNSIGNED|INT;
  427.   if(c==CONVLONG) typ=LONG;
  428.   if(c==CONVULONG) typ=UNSIGNED|LONG;
  429.   if(c==CONVFLOAT) typ=FLOAT;
  430.   if(c==CONVDOUBLE) typ=DOUBLE;
  431.   if(c==CONVPOINTER) typ=UNSIGNED|LONG;
  432.  
  433.   q1reg=q2reg=zreg=0;
  434.   if(p->q1.flags®) q1reg=p->q1.reg;
  435.   if(p->q2.flags®) q2reg=p->q2.reg;
  436.   if((p->z.flags&(REG|DREFOBJ))==REG) zreg=p->z.reg;
  437.  
  438.  
  439.   if((p->q1.flags&(KONST|DREFOBJ))==KONST){
  440.     eval_const(&p->q1.val,typ);
  441.     if(zleqto(vlong,l2zl(0L))&&zuleqto(vulong,ul2zul(0UL))&&zdeqto(vdouble,d2zd(0.0))){
  442.       if((typ&NQ)==FLOAT||(typ&NQ)==DOUBLE) q1reg=f31; else q1reg=r31;
  443.     }else{
  444.       if((typ&NQ)==FLOAT||(typ&NQ)==DOUBLE) reg=f1; else reg=t1;
  445.       if(c==ASSIGN&&zreg) reg=zreg;
  446.       if(c==SETRETURN&&p->z.reg) reg=p->z.reg;
  447.       if((c==MOD||c==DIV)&&(typ&NQ)<=LONG&&!regs[25]) reg=25; /* Linux-div */
  448.       if((typ&NQ)==FLOAT||(typ&NQ)==DOUBLE||c==DIV||c==SUB||c==ASSIGN||c==PUSH||c==SETRETURN||c==LSHIFT||c==RSHIFT||c==COMPARE){
  449.         load_reg(f,reg,&p->q1,typ,t1);
  450.         q1reg=reg;
  451.       }else{
  452.         if((typ&NQ)<=LONG){
  453.           if(!zulleq(vlong,l2zl(255L))||!zlleq(vlong,l2zl(255))||zlleq(vlong,l2zl(-1L))){
  454.             load_reg(f,reg,&p->q2,typ,t1);
  455.             q1reg=reg;
  456.           }
  457.         }
  458.       }
  459.     }
  460.   }else if(c!=ADDRESS){
  461.     if(p->q1.flags&&!q1reg){
  462.       if((typ&NQ)==FLOAT||(typ&NQ)==DOUBLE) reg=f1; else reg=t1;
  463.       if((c==ASSIGN||(c>=CONVCHAR&&c<=CONVULONG))&&zreg&&(reg-r31)*(zreg-r31)>0) reg=zreg;
  464.       if(c==SETRETURN&&p->z.reg) reg=p->z.reg;
  465.       if((p->q1.flags&DREFOBJ)||c==ADDI2P||c==SUBIFP) {typ1=POINTER;reg=t1;} else typ1=typ;
  466.       if(c==CALL) reg=vp;
  467.       if((c==MOD||c==DIV)&&(typ1&NQ)<=LONG&&!regs[25]) reg=25; /* Linux-div */
  468.       if((typ1&NQ)<=POINTER){
  469.         int m=p->q1.flags;
  470.         p->q1.flags&=~DREFOBJ;
  471.         load_reg(f,reg,&p->q1,typ1,t1);
  472.         p->q1.flags=m;
  473.         q1reg=reg;
  474.       }
  475.     }
  476.     if((p->q1.flags&DREFOBJ)&&(typ&NQ)<=POINTER){
  477.       if((typ&NQ)==FLOAT||(typ&NQ)==DOUBLE) reg=f1; else reg=t1;
  478.       if((c==ASSIGN||(c>=CONVCHAR&&c<=CONVULONG))&&zreg&®ok(zreg,typ,0)) reg=zreg;
  479.       if(c==SETRETURN&&p->z.reg) reg=p->z.reg;
  480.       if((c==MOD||c==DIV)&&(typ&NQ)<=LONG&&!regs[25]) reg=25; /* Linux-div */
  481.       if(c==ADDI2P||c==SUBIFP)
  482.         load_reg(f,reg,cam(IMM_IND,q1reg,-1,0),POINTER,t1);
  483.       else
  484.         load_reg(f,reg,cam(IMM_IND,q1reg,-1,0),typ,t1);
  485.       q1reg=reg;
  486.     }
  487.   }
  488.   if((p->q2.flags&(KONST|DREFOBJ))==KONST){
  489.     eval_const(&p->q2.val,typ);
  490.     if(zleqto(vlong,l2zl(0L))&&zuleqto(vulong,ul2zul(0UL))&&zdeqto(vdouble,d2zd(0.0))){
  491.       if((typ&NQ)==FLOAT||(typ&NQ)==DOUBLE) q2reg=f31; else q2reg=r31;
  492.     }else{
  493.       if((typ&NQ)==FLOAT||(typ&NQ)==DOUBLE) reg=f2; else reg=t2;
  494.       if((c==MOD||c==DIV)&&(typ&NQ)<=LONG&&!regs[26]) reg=26; /* Linux-div */
  495.       if((typ&NQ)==FLOAT||(typ&NQ)==DOUBLE){
  496.         load_reg(f,reg,&p->q2,typ,t2);
  497.         q2reg=reg;
  498.       }else{
  499.         if((typ&NQ)<=LONG){
  500.           if(!zulleq(vlong,l2zl(255L))||!zlleq(vlong,l2zl(255L))||zlleq(vlong,l2zl(-1L))){
  501.             load_reg(f,reg,&p->q2,typ,t2);
  502.             q2reg=reg;
  503.           }
  504.         }
  505.       }
  506.     }
  507.   }else{
  508.     if(p->q2.flags&&!q2reg){
  509.       if(p->q2.flags&DREFOBJ) typ1=POINTER; else typ1=typ;
  510.       if((typ1&NQ)==FLOAT||(typ1&NQ)==DOUBLE) reg=f2; else reg=t2;
  511.       if((c==MOD||c==DIV)&&(typ1&NQ)<=LONG&&!regs[26]) reg=26; /* Linux-div */
  512.       if((typ1&NQ)<=POINTER){
  513.         int m=p->q2.flags;
  514.         p->q2.flags&=~DREFOBJ;
  515.         load_reg(f,reg,&p->q2,typ1,t2);
  516.         p->q2.flags=m;
  517.         q2reg=reg;
  518.       }
  519.     }
  520.     if((p->q2.flags&DREFOBJ)&&(typ&NQ)<=POINTER){
  521.       if((typ&NQ)==FLOAT||(typ&NQ)==DOUBLE) reg=f2; else reg=t2;
  522.       if((c==MOD||c==DIV)&&(typ&NQ)<=LONG&&!regs[26]) reg=26; /* Linux-div */
  523.       load_reg(f,reg,cam(IMM_IND,q2reg,-1,0),typ,t2);
  524.       q2reg=reg;
  525.     }
  526.   }
  527.   if(p->z.flags&&!isreg(z)){
  528.     typ=p->typf;
  529.     if((typ&NQ)==FLOAT||(typ&NQ)==DOUBLE) zreg=f3; else zreg=t3;
  530.     if((c==MOD||c==DIV)&&(typ&NQ)<=LONG&&!regs[28]) zreg=28; /* Linux-div */
  531.   }
  532.   if(q1reg){ p->q1.flags=REG; p->q1.reg=q1reg;}
  533.   if(q2reg){ p->q2.flags=REG; p->q2.reg=q2reg;}
  534.   return(p);
  535. }
  536. static long pof2(zulong x)
  537. /*  Yields log2(x)+1 oder 0. */
  538. {
  539.     zulong p;int ln=1;
  540.     p=ul2zul(1L);
  541.     while(ln<=64&&zulleq(p,x)){
  542.         if(zuleqto(x,p)) return(ln);
  543.         ln++;p=zuladd(p,p);
  544.     }
  545.     return(0);
  546. }
  547. static void pr(FILE *f,struct IC *p)
  548. /*  Writes the destination register to the real destination if necessary.   */
  549. {
  550.   int typ=p->typf;
  551.   if(p->z.flags){
  552.     if(p->code==ADDRESS||p->code==ADDI2P||p->code==SUBIFP) typ=POINTER;
  553.     if(!isreg(z)){
  554.       if(p->z.flags&DREFOBJ){
  555.         if(p->z.flags®){
  556.           store_reg(f,zreg,cam(IMM_IND,p->z.reg,-1,0),typ);
  557.         }else{
  558.           int r,m;
  559.           if(t1==zreg) r=t2; else r=t1;
  560.           m=p->z.flags;
  561.           p->z.flags&=~DREFOBJ;
  562.           load_reg(f,r,&p->z,POINTER,r);
  563.           p->z.flags=m;
  564.           store_reg(f,zreg,cam(IMM_IND,r,balign(&p->z),0),typ);
  565.         }
  566.       }else{
  567.         store_reg(f,zreg,&p->z,typ);
  568.       }
  569.     }else{
  570.       if(p->z.reg!=zreg)
  571.         move_reg(f,zreg,p->z.reg);
  572.     }
  573.   }
  574. }
  575.  
  576. static void probj2(FILE *f,struct obj *p,int t)
  577. /*  Prints an object.                               */
  578. {
  579.   if(p->am){
  580.     if(p->am->flags==REG_IND) ierror(0);
  581.     if(p->am->flags==IMM_IND) fprintf(f,"%ld(%s)",p->am->offset,regnames[p->am->base]);
  582.     return;
  583.   }
  584.   if(p->flags&DREFOBJ) fprintf(f,"(");
  585.   if(p->flags&VAR) {
  586.     if(p->v->storage_class==AUTO||p->v->storage_class==REGISTER){
  587.       if(p->flags®){
  588.         fprintf(f,"%s",regnames[p->reg]);
  589.       }else{
  590.         long of=zl2l(p->v->offset);
  591.         if(of>=0)
  592.           of+=frameoffset+zl2l(p->val.vlong);
  593.         else
  594.           of=-of-zl2l(maxalign)+framesize+zl2l(p->val.vlong);
  595.         if(of>32767) ierror(0);
  596.         fprintf(f,"%ld(%s)",of,regnames[sp]);
  597.       }
  598.     }else{
  599.       if(!zleqto(l2zl(0L),p->val.vlong)){printval(f,&p->val,LONG,0);fprintf(f,"+");}
  600.       if(p->v->storage_class==STATIC&&(p->v->vtyp->flags&NQ)!=FUNKT){
  601.         fprintf(f,"%s%ld",labprefix,zl2l(p->v->offset));
  602.       }else{
  603.         fprintf(f,"%s%s",idprefix,p->v->identifier);
  604.       }
  605.     }
  606.   }
  607.   if((p->flags®)&&!(p->flags&VAR)) fprintf(f,"%s",regnames[p->reg]);
  608.   if(p->flags&KONST){
  609.     printval(f,&p->val,t&NU,0);
  610.   }
  611.   if(p->flags&DREFOBJ) fprintf(f,")");
  612. }
  613. static void function_top(FILE *f,struct Var *v,long offset,long maxpushed)
  614. /*  Generates function top.                             */
  615. {
  616.   int i;
  617.    fprintf(f,"\t.set\tnoat\n");
  618.   if(section!=CODE){fprintf(f,codename);section=CODE;}
  619.   if(v->storage_class==EXTERN) fprintf(f,"\t.global\t%s%s\n",idprefix,v->identifier);
  620.   fprintf(f,"\t.ent\t%s%s\n",idprefix,v->identifier);
  621.   fprintf(f,"%s%s:\n",idprefix,v->identifier);
  622.   if(function_calls) fprintf(f,"\tldgp\t%s,0(%s)\n",regnames[gp],regnames[vp]);
  623.   fprintf(f,"%s%s..ng:\n",idprefix,v->identifier);
  624.   framesize=offset+maxpushed;
  625.   if(function_calls) framesize+=8; /* lr */
  626.   for(i=1;i<=MAXR;i++)
  627.     if(regused[i]&&!regscratch[i]&&!regsa[i])
  628.       framesize+=8;
  629.   framesize=((framesize+16-1)/16)*16;
  630.   if(framesize>32767) ierror(0);
  631.   if(framesize) fprintf(f,"\tlda\t%s,%ld(%s)\n",regnames[sp],-framesize,regnames[sp]);
  632.   fprintf(f,"\t.frame\t%s,%ld,%s,0\n",regnames[sp],framesize,regnames[lr]);
  633.   frameoffset=maxpushed;
  634.   if(function_calls){
  635.     fprintf(f,"\tstq\t%s,%ld(%s)\n",regnames[lr],frameoffset,regnames[sp]);
  636.     frameoffset+=8;
  637.   }
  638.   for(i=1;i<=MAXR;i++){
  639.     if(regused[i]&&!regscratch[i]&&!regsa[i]){
  640.       if(i<=32){
  641.         fprintf(f,"\tstq\t%s,%ld(%s)\n",regnames[i],frameoffset,regnames[sp]);
  642.       }else{
  643.         fprintf(f,"\tstt\t%s,%ld(%s)\n",regnames[i],frameoffset,regnames[sp]);
  644.       }
  645.       frameoffset+=8;
  646.     }
  647.   }
  648.   fprintf(f,"\t.mask\t0x4000000,%ld\n",-framesize);
  649.   fprintf(f,"\t.prologue\t%c\n",function_calls?'1':'0');
  650. }
  651. static void function_bottom(FILE *f,struct Var *v,long offset,long maxpushed)
  652. /*  Generates function bottom.                          */
  653. {
  654.   int i;
  655.   frameoffset=maxpushed;
  656.   if(function_calls){
  657.     fprintf(f,"\tldq\t%s,%ld(%s)\n",regnames[lr],frameoffset,regnames[sp]);
  658.     frameoffset+=8;
  659.   }
  660.   for(i=1;i<=MAXR;i++){
  661.     if(regused[i]&&!regscratch[i]&&!regsa[i]){
  662.       if(i<=32){
  663.         fprintf(f,"\tldq\t%s,%ld(%s)\n",regnames[i],frameoffset,regnames[sp]);
  664.       }else{
  665.         fprintf(f,"\tldt\t%s,%ld(%s)\n",regnames[i],frameoffset,regnames[sp]);
  666.       }
  667.       frameoffset+=8;
  668.     }
  669.   }
  670.   if(framesize) fprintf(f,"\tlda\t%s,%ld(%s)\n",regnames[sp],framesize,regnames[sp]);
  671.   fprintf(f,"\tret\t%s,(%s),1\n",regnames[r31],regnames[lr]);
  672.   fprintf(f,"\t.end\t%s%s\n",idprefix,v->identifier);
  673.   fprintf(f,"\t.type\t%s%s,@function\n",idprefix,v->identifier);
  674.   fprintf(f,"\t.size\t%s%s,$-%s%s\n",idprefix,v->identifier,idprefix,v->identifier);
  675. }
  676. static int is_const(struct Typ *t)
  677. /*  Tests if a type can be placed in the code-section.  */
  678. {
  679.   if(!(t->flags&(CONST|STRINGCONST))){
  680.     do{
  681.       if(t->flags&(CONST|STRINGCONST)) return(1);
  682.       if((t->flags&NQ)!=ARRAY) return(0);
  683.       t=t->next;
  684.     }while(1);
  685.   }else return(1);
  686. }
  687. static int balign(struct obj *o)
  688. /*  Liefert die unteren 3 Bits des Objekts. -1 wenn unklar. */
  689. {
  690.   int sc;
  691.   if(o->flags&DREFOBJ) return -1;
  692.   if(o->am) return o->am->align;
  693.   if(!(o->flags&VAR)) ierror(0);
  694.   sc=o->v->storage_class;
  695.   if(sc==EXTERN||sc==STATIC){
  696.     /* Alle statischen Daten werden vom cg auf 64bit alignt. */
  697.     return zl2l(zland(o->val.vlong,l2zl(7L)));
  698.   }
  699.   if(sc==AUTO||sc==REGISTER){
  700.     zlong of=o->v->offset;
  701.     if(!zlleq(l2zl(0L),of))
  702.       of=zlsub(l2zl(0L),zladd(of,maxalign));
  703.     return zl2l(zland(zladd(of,o->val.vlong),l2zl(7L)));
  704.   }
  705.   ierror(0);
  706. }
  707.  
  708. /* Routinen fuer Debug-Informationen mit stabs. */
  709.  
  710. static int debug_blabel,debug_elabel;
  711. static int debug_type(FILE *,struct Typ *);
  712. static void debug_init(FILE *,struct Var *);
  713. static void debug_exit(FILE *,struct Var *);
  714. static void debug_var(FILE *,struct obj *);
  715. static void debug_IC(FILE *,struct IC *);
  716. static void debug_cleanup(FILE *);
  717.  
  718. static int debug_type(FILE *f,struct Typ *t)
  719.      /* Liefert Typindex.  */
  720. {
  721.   return t->flags&NU;
  722. }
  723. static void debug_init(FILE *f,struct Var *v)
  724.      /* Debug-Infos. Wird am Anfang von gen_code aufgerufen. */
  725. {
  726.   static int did_header;
  727.   if(!did_header){
  728.     fprintf(f,"\t.stabs \"\",100,0,0,%stext0\n",labprefix);
  729.     fprintf(f,"\t.stabs \"%s\",100,0,0,%stext0\n",errfname,labprefix);
  730.     fprintf(f,"\t.text\n%stext0:\n",labprefix);section=CODE;
  731.     fprintf(f,"\t.stabs\t\"char:t%d=r1;-128;127;\",128,0,0,0\n",CHAR);
  732.     fprintf(f,"\t.stabs\t\"short:t%d=r1;-32768;32767;\",128,0,0,0\n",SHORT);
  733.     fprintf(f,"\t.stabs\t\"int:t%d=r1;-2147483648;2147483647;\",128,0,0,0\n",INT);
  734.     fprintf(f,"\t.stabs\t\"long:t%d=r1;001000000000000000000000;000777777777777777777777;\",128,0,0,0\n",LONG);
  735.     fprintf(f,"\t.stabs\t\"unsigned char:t%d=r1;0;255;\",128,0,0,0\n",UNSIGNED|CHAR);
  736.     fprintf(f,"\t.stabs\t\"unsigned short:t%d=r1;0;65535;\",128,0,0,0\n",UNSIGNED|SHORT);
  737.     fprintf(f,"\t.stabs\t\"unsigned int:t%d=r1;0;-1;\",128,0,0,0\n",UNSIGNED|INT);
  738.     fprintf(f,"\t.stabs\t\"unsigned long:t%d=r1;0;-1;\",128,0,0,0\n",UNSIGNED|LONG);
  739.     fprintf(f,"\t.stabs\t\"float:t%d=r1;4;0;\",128,0,0,0\n",FLOAT);
  740.     fprintf(f,"\t.stabs\t\"double:t%d=r1;8;0;\",128,0,0,0\n",DOUBLE);
  741.     fprintf(f,"\t.stabs\t\"void:t%d=%d;8;0;\",128,0,0,0\n",VOID,VOID);
  742.     did_header=1;
  743.   }
  744.   fprintf(f,"\t.stabs\t\"%s:F%d\",36,0,0,%s%s\n",v->identifier,debug_type(f,v->vtyp->next),idprefix,v->identifier);
  745.   debug_blabel=++label;debug_elabel=++label;
  746. }
  747. static void debug_exit(FILE *f,struct Var *v)
  748.      /* Debug-Infos. Wird am Ende von gen_code aufgerufen. */
  749. {
  750.   struct IC *p;
  751.   fprintf(f,"\t.stabn\t192,0,0,%s%d\n",labprefix,debug_blabel);
  752.   fprintf(f,"\t.stabn\t224,0,0,%s%d\n",labprefix,debug_elabel);
  753.   for(p=first_ic;p;p=p->next){
  754.     if(p->q1.flags&VAR) debug_var(f,&p->q1);
  755.     if(p->q2.flags&VAR) debug_var(f,&p->q2);
  756.     if(p->z.flags&VAR) debug_var(f,&p->z);
  757.   }
  758. }
  759. static void debug_var(FILE *f,struct obj *o)
  760.      /* Debug-Infos fuer eine Variable ausgeben. */
  761. {
  762.   struct Var *v=o->v; int td;
  763.   if(!*v->identifier) return;
  764.   td=debug_type(f,v->vtyp);
  765.   if(td==FUNKT) return;
  766.   if(o->flags®){
  767.     fprintf(f,"\t.stabs\t\"%s:r%d\",0x40,0,0,%d\n",v->identifier,td,o->reg-1);
  768.     return;
  769.   }
  770.   if(v->storage_class==AUTO||v->storage_class==REGISTER){
  771.     long of=zl2l(v->offset);
  772.     if(!zlleq(l2zl(0L),v->offset)){
  773.       of=-of-zl2l(maxalign)+framesize;
  774.       fprintf(f,"#\toffset %ld:\n",of);
  775.       fprintf(f,"\t.stabs\t\"%s:p%d\",0x80,0,0,%ld\n",v->identifier,td,of-framesize);
  776.     }else{
  777.       of+=frameoffset;
  778.       fprintf(f,"#\toffset %ld:\n",of);
  779.       fprintf(f,"\t.stabs\t\"%s:%d\",0x80,0,0,%ld\n",v->identifier,td,of-framesize);
  780.     }
  781.     return;
  782.   }
  783.   ierror(td);
  784. }
  785. static void debug_IC(FILE *f,struct IC *p)
  786.      /* Debug-Infos. Wird fuer jedes IC aufgerufen. */
  787. {
  788.   static int lastline;int lab;
  789.   printf("%d",p->line);pric2(stdout,p);
  790.   if(!p->prev)
  791.     fprintf(f,"%s%d:\n",labprefix,debug_blabel);
  792. /*   if(p->q1.flags&VAR) debug_var(f,&p->q1); */
  793. /*   if(p->q2.flags&VAR) debug_var(f,&p->q2); */
  794. /*   if(p->z.flags&VAR) debug_var(f,&p->z); */
  795.   if(p->line&&p->line!=lastline){
  796.     lab=++label;lastline=p->line;
  797.     fprintf(f,"%s%d:\n",labprefix,lab);
  798.     fprintf(f,"\t.stabn\t68,0,%d,%s%d\n",lastline,labprefix,lab);
  799.   }
  800.   if(!p->next) fprintf(f,"%s%d:\n",labprefix,debug_elabel);
  801. }
  802. static void debug_cleanup(FILE *f)
  803.      /* Debug-Infos. Wird in cleanup_cg aufgerufen. */
  804. {
  805. }
  806.  
  807.  
  808. /****************************************/
  809. /*  End of private data and functions.  */
  810. /****************************************/
  811.  
  812.  
  813. int init_cg(void)
  814. /*  Does necessary initializations for the code-generator. Gets called  */
  815. /*  once at the beginning and should return 0 in case of problems.      */
  816. {
  817.   int i;
  818.   /*  Initialize some values which cannot be statically initialized   */
  819.   /*  because they are stored in the target's arithmetic.             */
  820.   maxalign=l2zl(8L);
  821.   char_bit=l2zl(8L);
  822.   for(i=0;i<16;i++){
  823.     sizetab[i]=l2zl(msizetab[i]);
  824.     align[i]=l2zl(malign[i]);
  825.   }
  826.   for(i= 1;i<=32;i++) {regsize[i]=l2zl(8L);regtype[i]=<yp;}
  827.   for(i=33;i<=64;i++) {regsize[i]=l2zl(8L);regtype[i]=<yp;}
  828.  
  829.   /*  Use multiple ccs.   */
  830.   multiple_ccs=0; /* not yet */
  831.  
  832.   /*  Initialize the min/max-settings. Note that the types of the     */
  833.   /*  host system may be different from the target system and you may */
  834.   /*  only use the smallest maximum values ANSI guarantees if you     */
  835.   /*  want to be portable.                                            */
  836.   /*  That's the reason for the subtraction in t_min[INT]. Long could */
  837.   /*  be unable to represent -2147483648 on the host system.          */
  838.   t_min[UNSIGNED|CHAR]=t_min[UNSIGNED|SHORT]=t_min[UNSIGNED|INT]=t_min[UNSIGNED|LONG]=l2zl(0L);
  839.   t_min[CHAR]=l2zl(-128L);
  840.   t_min[SHORT]=l2zl(-32768L);
  841.   t_min[INT]=zlsub(l2zl(-2147483647L),l2zl(1L));
  842.   t_min[LONG]=zllshift(l2zl(-1L),l2zl(63L));
  843.   t_max[CHAR]=ul2zul(127UL);
  844.   t_max[SHORT]=ul2zul(32767UL);
  845.   t_max[INT]=ul2zul(2147483647UL);
  846.   t_max[LONG]=zulsub(zulrshift(ul2zul(1UL),ul2zul(63UL)),ul2zul(1UL));
  847.   t_max[UNSIGNED|CHAR]=ul2zul(255UL);
  848.   t_max[UNSIGNED|SHORT]=ul2zul(65535UL);
  849.   t_max[UNSIGNED|INT]=ul2zul(4294967295UL);
  850.   t_max[UNSIGNED|LONG]=zulkompl(ul2zul(0UL));
  851.   /*  Reserve a few registers for use by the code-generator.      */
  852.   /*  This is not optimal but simple.                             */
  853.   regsa[t1]=regsa[t2]=regsa[t3]=regsa[t4]=regsa[t5]=1;
  854.   regsa[f1]=regsa[f2]=regsa[f3]=1;
  855.   regsa[sp]=regsa[gp]=regsa[sd]=1;
  856.   regsa[lr]=regsa[r31]=regsa[f31]=1;
  857.   regscratch[t1]=regscratch[t2]=regscratch[t3]=regscratch[t4]=regscratch[t5]=0;
  858.   regscratch[f1]=regscratch[f2]=regscratch[f3]=0;
  859.   regscratch[sp]=regscratch[gp]=regscratch[sd]=0;
  860.   regscratch[lr]=regscratch[r31]=regscratch[f31]=0;
  861.   /* reserve at - noch aendern */
  862.   /* regsa[29]=1;regscratch[29]=0; */
  863.   /* Debug stabs? */
  864.   stabs=(g_flags[5]&USEDFLAG);
  865.   return(1);
  866. }
  867.  
  868. int freturn(struct Typ *t)
  869. /*  Returns the register in which variables of type t are returned. */
  870. /*  If the value cannot be returned in a register returns 0.        */
  871. /*  A pointer MUST be returned in a register. The code-generator    */
  872. /*  has to simulate a pseudo register if necessary.                 */
  873. {
  874.   if((t->flags&NQ)==FLOAT||(t->flags&NQ)==DOUBLE) return(33);
  875.   if((t->flags&NQ)==STRUCT||(t->flags&NQ)==UNION) return(0);
  876.   if(zlleq(szof(t),l2zl(8L))) return(1); else return(0);
  877. }
  878.  
  879. int regok(int r,int t,int mode)
  880. /*  Returns 0 if register r cannot store variables of   */
  881. /*  type t. If t==POINTER and mode!=0 then it returns   */
  882. /*  non-zero only if the register can store a pointer   */
  883. /*  and dereference a pointer to mode.                  */
  884. {
  885.   if(r==0) return(0);
  886.   t&=NQ;
  887.   if(t==0) return(0);
  888.   if((t==FLOAT||t==DOUBLE)&&r>=33&&r<=64) return(1);
  889.   if(t==POINTER&&r>=1&&r<=32) return(1);
  890.   if(t>=CHAR&&t<=LONG&&r>=1&&r<=32) return(1);
  891.   return(0);
  892. }
  893.  
  894. int dangerous_IC(struct IC *p)
  895. /*  Returns zero if the IC p can be safely executed     */
  896. /*  without danger of exceptions or similar things.     */
  897. /*  vbcc may generate code in which non-dangerous ICs   */
  898. /*  are sometimes executed although control-flow may    */
  899. /*  never reach them (mainly when moving computations   */
  900. /*  out of loops).                                      */
  901. /*  Typical ICs that generate exceptions on some        */
  902. /*  machines are:                                       */
  903. /*      - accesses via pointers                         */
  904. /*      - division/modulo                               */
  905. /*      - overflow on signed integer/floats             */
  906. {
  907.   int c=p->code;
  908.   if((p->q1.flags&DREFOBJ)||(p->q2.flags&DREFOBJ)||(p->z.flags&DREFOBJ))
  909.     return(0);
  910.   if((c==DIV||c==MOD)&&!(p->q2.flags&KONST))
  911.     return(1);
  912.   return(0);
  913. }
  914.  
  915. int must_convert(np p,int t)
  916. /*  Returns zero if code for converting np to type t    */
  917. /*  can be omitted.                                     */
  918. /*  On the PowerPC cpu pointers and 32bit               */
  919. /*  integers have the same representation and can use   */
  920. /*  the same registers.                                 */
  921. {
  922.   int o=p->ntyp->flags,op=o&NQ,tp=t&NQ;
  923.   if((op==LONG||op==POINTER)&&(tp==LONG||tp==POINTER)) return 0;
  924.   return(1);
  925. }
  926.  
  927. void gen_ds(FILE *f,zlong size,struct Typ *t)
  928. /*  This function has to create <size> bytes of storage */
  929. /*  initialized with zero.                              */
  930. {
  931.   if(newobj){
  932.    size=zlmult(zldiv(zladd(size,l2zl(7L)),l2zl(8L)),l2zl(8L));
  933.     printzl(f,size);
  934.   }else{
  935.     fprintf(f,"\t.zero\t");
  936.     printzl(f,size);
  937.   }
  938.   fprintf(f,"\n");
  939.   newobj=0;
  940. }
  941.  
  942. void gen_align(FILE *f,zlong align)
  943. /*  This function has to make sure the next data is     */
  944. /*  aligned to multiples of <align> bytes.              */
  945. {
  946.   fprintf(f,"\t.align\t3\n");
  947. }
  948.  
  949. void gen_var_head(FILE *f,struct Var *v)
  950. /*  This function has to create the head of a variable  */
  951. /*  definition, i.e. the label and information for      */
  952. /*  linkage etc.                                        */
  953. {
  954.   int constflag;
  955.   if(v->clist) constflag=is_const(v->vtyp);
  956.   if(v->storage_class==STATIC){
  957.     if((v->vtyp->flags&NQ)==FUNKT) return;
  958.     if(v->clist&&(!constflag||(g_flags[2]&USEDFLAG))&§ion!=DATA){fprintf(f,dataname);section=DATA;}
  959.     if(v->clist&&constflag&&!(g_flags[2]&USEDFLAG)&§ion!=CODE){fprintf(f,codename);section=CODE;}
  960.     if(!v->clist&§ion!=BSS){fprintf(f,bssname);section=BSS;}
  961.     fprintf(f,"\t.type\t%s%ld,@object\n",labprefix,zl2l(v->offset));
  962.     fprintf(f,"\t.size\t%s%ld,%ld\n",labprefix,zl2l(v->offset),zl2l(szof(v->vtyp)));
  963.     if(section!=BSS) fprintf(f,"\t.align\t3\n%s%ld:\n",labprefix,zl2l(v->offset));
  964.     else fprintf(f,"\t.lcomm\t%s%ld,",labprefix,zl2l(v->offset));
  965.     newobj=1;
  966.   }
  967.   if(v->storage_class==EXTERN){
  968.     fprintf(f,"\t.global\t%s%s\n",idprefix,v->identifier);
  969.     if(v->flags&(DEFINED|TENTATIVE)){
  970.       if(v->clist&&(!constflag||(g_flags[2]&USEDFLAG))&§ion!=DATA){fprintf(f,dataname);section=DATA;}
  971.       if(v->clist&&constflag&&!(g_flags[2]&USEDFLAG)&§ion!=CODE){fprintf(f,codename);section=CODE;}
  972.       if(!v->clist&§ion!=BSS){fprintf(f,bssname);section=BSS;}
  973.       fprintf(f,"\t.type\t%s%s,@object\n",idprefix,v->identifier);
  974.       fprintf(f,"\t.size\t%s%s,%ld\n",idprefix,v->identifier,zl2l(szof(v->vtyp)));
  975.       if(section!=BSS) fprintf(f,"\t.align\t3\n%s%s:\n",idprefix,v->identifier);
  976.       else fprintf(f,"\t.comm\t%s%s,",idprefix,v->identifier);
  977.       newobj=1;
  978.     }
  979.   }
  980. }
  981.  
  982. void gen_dc(FILE *f,int t,struct const_list *p)
  983. /*  This function has to create static storage          */
  984. /*  initialized with const-list p.                      */
  985. {
  986.   if((t&NQ)==POINTER) t=UNSIGNED|LONG;
  987.   fprintf(f,"\t.%s\t",dct[t&NQ]);
  988.   if(!p->tree){
  989.     if((t&NQ)==FLOAT||(t&NQ)==DOUBLE){
  990.       /*  auch wieder nicht sehr schoen und IEEE noetig   */
  991.       unsigned char *ip;
  992.       ip=(unsigned char *)&p->val.vdouble;
  993.       fprintf(f,"0x%02x%02x%02x%02x",ip[3],ip[2],ip[1],ip[0]);
  994.       if((t&NQ)==DOUBLE){
  995.         fprintf(f,",0x%02x%02x%02x%02x",ip[7],ip[6],ip[5],ip[4]);
  996.       }
  997.     }else{
  998.       printval(f,&p->val,t&NU,0);
  999.     }
  1000.   }else{
  1001.     if(p->tree->o.am) ierror(9);
  1002.     probj2(f,&p->tree->o,t&NU);
  1003.   }
  1004.   fprintf(f,"\n");newobj=0;
  1005. }
  1006.  
  1007.  
  1008. /*  The main code-generation routine.                   */
  1009. /*  f is the stream the code should be written to.      */
  1010. /*  p is a pointer to a doubly linked list of ICs       */
  1011. /*  containing the function body to generate code for.  */
  1012. /*  v is a pointer to the function.                     */
  1013. /*  offset is the size of the stackframe the function   */
  1014. /*  needs for local variables.                          */
  1015.  
  1016. void gen_code(FILE *f,struct IC *p,struct Var *v,zlong offset)
  1017. /*  The main code-generation.                                           */
  1018. {
  1019.   int addbuf,c,t,cmpreg,cmpflag,wasnoreg,i,varargs=0,fixargs;struct IC *m;
  1020.   long pushed,maxpushed;
  1021.   if(DEBUG&1) printf("gen_code()\n");
  1022.   if(stabs) debug_init(f,v);
  1023.   for(c=1;c<=MAXR;c++){regs[c]=regsa[c];st[c]=ESGN;}
  1024.   /* We do a pass over the code to retrieve some info and prepare certain optimizations */
  1025.   addbuf=0;maxpushed=0;
  1026.   for(m=p;m;m=m->next){
  1027.     c=m->code;t=m->typf&NU;
  1028.     if(c==ALLOCREG) {regs[m->q1.reg]=1;continue;}
  1029.     if(c==FREEREG) {regs[m->q1.reg]=0;continue;}
  1030.     if(c==COMPARE&&(m->q2.flags&KONST)){
  1031.       eval_const(&m->q2.val,t);
  1032.       if(zleqto(vlong,l2zl(0L))&&zdeqto(vdouble,d2zd(0.0))){
  1033.         m->q2.flags=0;m->code=c=TEST;
  1034.       }
  1035.     }
  1036.     if((t&NQ)<=LONG&&(m->q2.flags&KONST)&&(c==MULT||c==DIV||(c==MOD&&(t&UNSIGNED)))){
  1037.       eval_const(&m->q2.val,t);
  1038.       i=pof2(vulong);
  1039.       if(i){
  1040.         if(c==MOD){
  1041.           vlong=zlsub(vlong,l2zl(1L));
  1042.           m->code=AND;
  1043.         }else{
  1044.           vlong=l2zl(i-1);
  1045.           if(c==DIV) m->code=RSHIFT; else m->code=LSHIFT;
  1046.         }
  1047.         c=m->code;
  1048.         if((t&NU)==CHAR) m->q2.val.vchar=zl2zc(vlong);
  1049.         if((t&NU)==SHORT) m->q2.val.vshort=zl2zs(vlong);
  1050.         if((t&NU)==INT) m->q2.val.vint=zl2zi(vlong);
  1051.         if((t&NU)==LONG) m->q2.val.vlong=vlong;
  1052.         vulong=zl2zul(vlong);
  1053.         if((t&NU)==(UNSIGNED|CHAR)) m->q2.val.vuchar=zul2zuc(vulong);
  1054.         if((t&NU)==(UNSIGNED|SHORT)) m->q2.val.vushort=zul2zus(vulong);
  1055.         if((t&NU)==(UNSIGNED|INT))  m->q2.val.vuint=zul2zui(vulong);
  1056.         if((t&NU)==(UNSIGNED|LONG)) m->q2.val.vulong=vulong;
  1057.       }
  1058.     }
  1059.     /* Need one stack slot for transfrring between integer and floating-point registers. */
  1060.     t&=NQ;
  1061.     if(c==CONVDOUBLE&&t<=LONG&&addbuf<8) addbuf=8;
  1062.     if(c==CONVFLOAT&&t<=LONG&&addbuf<8) addbuf=8;
  1063. /*     if(t==DOUBLE&&c>=CONVCHAR&&c<=CONVLONG&&addbuf<8) addbuf=8; */
  1064. /*     if(t==FLOAT&&c>=CONVCHAR&&c<=CONVLONG&&addbuf<8) addbuf=8;  */
  1065.     if(t==DOUBLE&&c!=CONVFLOAT&&addbuf<8) addbuf=8;
  1066.     if(t==FLOAT&&c!=CONVDOUBLE&&addbuf<8) addbuf=8;
  1067.     /* May need one stack slot for inline memcpy. */
  1068. /*     if((c==ASSIGN||c==PUSH)&&t>=POINTER&&addbuf<8) addbuf=8; */
  1069.     /* Need additional stack slots for passing function arguments. */
  1070.     if(c==CALL&&maxpushed<zl2l(m->q2.val.vlong)) maxpushed=zl2l(m->q2.val.vlong);
  1071.     if(c==CALL&&(m->q1.flags&VAR)&&!strcmp(m->q1.v->identifier,"__va_start")) varargs=1;
  1072.     /* Need up to 4 stack slots for calling div/mod-functions. */
  1073.     if((c==DIV||c==MOD)&&(p->typf&NQ)<=LONG&&addbuf<32){
  1074.       if(regs[25]||regs[26]||regs[28]||regs[29]) addbuf=32;
  1075.     }
  1076.   }
  1077.   /* Noch nicht ok. */
  1078.   if(varargs){
  1079.     fixargs=0;
  1080.     for(i=0;i<v->vtyp->exact->count;i++){
  1081.       c=(*v->vtyp->exact->sl)[i].styp->flags&NQ;
  1082.       if(c<=POINTER) fixargs++;
  1083.     }
  1084.     if(fixargs<6) addbuf+=(6-fixargs)*16;
  1085.   }
  1086.   function_top(f,v,zl2l(offset+addbuf),maxpushed);
  1087.   if(varargs){
  1088.     for(i=fixargs+1;i<=6;i++){
  1089.       fprintf(f,"\tstq\t%s,%d(%s)\n",regnames[16+i],framesize-(7-i)*16,regnames[sp]);
  1090.       fprintf(f,"\tstt\t%s,%d(%s)\n",regnames[48+i],framesize-(7-i)*16+8,regnames[sp]);
  1091.     }
  1092.   }
  1093.   pushed=0;
  1094.   for(;p;pr(f,p),p=p->next){
  1095.     if(DEBUG) pric2(stdout,p);
  1096.     if(stabs) debug_IC(f,p);
  1097.     c=p->code;t=p->typf;
  1098.     if(c==NOP) continue;
  1099.     if(c==ALLOCREG) {regs[p->q1.reg]=1;continue;}
  1100.     if(c==FREEREG) {regs[p->q1.reg]=0;continue;}
  1101.     if(c==LABEL||(c>=BEQ&&c<=BRA)){
  1102.       int i;
  1103.       for(i=1;i<=32;i++)
  1104.         if(regs[i]&&!regsa[i]) extend(f,i);
  1105.     }
  1106.     if(c==LABEL) {fprintf(f,"%s%d:\n",labprefix,t);continue;}
  1107.     if(c==BRA) {fprintf(f,"\tbr\t%s%d\n",labprefix,t);continue;}
  1108.     if(c>=BEQ&&c<BRA){
  1109.       if(cmpflag){
  1110.         fprintf(f,"\t%sb%s\t%s,%s%d\n",cmpreg<=32?"":"f",cmpflag<0?"eq":"ne",regnames[cmpreg],labprefix,t);
  1111.       }else{
  1112.         fprintf(f,"\t%sb%s\t%s,%s%d\n",cmpreg<=32?"":"f",ccs[c-BEQ],regnames[cmpreg],labprefix,t);
  1113.       }
  1114.       continue;
  1115.     }
  1116.     if(c==MOVETOREG){
  1117.       load_reg(f,p->z.reg,&p->q1,p->z.reg<=32?LONG:DOUBLE,0);
  1118.       p->z.flags=0;
  1119.       continue;
  1120.     }
  1121.     if(c==MOVEFROMREG){
  1122.       store_reg(f,p->q1.reg,&p->z,p->q1.reg<=32?LONG:DOUBLE);
  1123.       p->z.flags=0;
  1124.       continue;
  1125.     }
  1126.     if((t&NQ)==POINTER) t=(t-POINTER+LONG)|UNSIGNED;
  1127.     if((c==ASSIGN||c==PUSH)&&((t&NQ)>POINTER||((t&NQ)==CHAR&&zl2l(p->q2.val.vlong)!=1))){
  1128.       zlong size; struct obj loops;
  1129.       int salign,dalign,cl,a1,a2,mr,ms;
  1130.       size=p->q2.val.vlong;
  1131.       salign=balign(&p->q1);
  1132.       if(c==PUSH) dalign=0; else dalign=balign(&p->z);
  1133.       if(salign>=0&&dalign>=0&&(salign&3)==(dalign&3)){
  1134.         a1=t1; a2=t2;
  1135.       }else{
  1136.         if(!helpl) helpl=++label;
  1137.         cl=0;mr=0;ms=0;
  1138.         for(i=1;i<=32;i++){
  1139.           if(i!=17&&i!=18&&i!=19&®used[i]&&!regscratch[i]&&!regs[i]) mr=i;
  1140.           if(regs[i]&®scratch[i]) ms=1;
  1141.         }
  1142.         if(mr==0) mr=t3;
  1143.         if(regs[17]||regs[18]||regs[19]||function_calls==0) ms=1;
  1144.         if(ms) fprintf(f,"\tlda\t%s,%s%d\n",regnames[mr],labprefix,helpl);
  1145.         if(regs[17]) fprintf(f,"\tstq\t%s,%d(%s)\n",regnames[17],8*cl++,regnames[mr]);
  1146.         if(regs[18]) fprintf(f,"\tstq\t%s,%d(%s)\n",regnames[18],8*cl++,regnames[mr]);
  1147.         if(regs[19]) fprintf(f,"\tstq\t%s,%d(%s)\n",regnames[19],8*cl++,regnames[mr]);
  1148.         a1=18;a2=17;
  1149.         if(p->z.am&&p->z.am->base==18) ierror(0);
  1150.         if(!p->z.am&&(p->z.flags®)&&p->z.reg==18) ierror(0);
  1151.       }
  1152.       if(p->q1.flags&DREFOBJ){
  1153.         p->q1.flags&=~DREFOBJ;
  1154.         load_reg(f,a1,&p->q1,POINTER,a1);
  1155.         p->q1.flags|=DREFOBJ;
  1156.       }else{
  1157.         load_address(f,a1,&p->q1,POINTER);
  1158.       }
  1159.       if(p->z.flags&DREFOBJ){
  1160.         p->z.flags&=~DREFOBJ;
  1161.         load_reg(f,a2,&p->z,POINTER,a2);
  1162.         p->z.flags|=DREFOBJ;
  1163.       }else{
  1164.         if(c==PUSH){
  1165.           fprintf(f,"\tlda\t%s,%ld(%s)\n",regnames[a2],pushed,regnames[sp]);
  1166.           pushed+=zl2l(p->q2.val.vlong);
  1167.         }else{
  1168.           load_address(f,a2,&p->z,POINTER);
  1169.         }
  1170.       }
  1171.       if(salign>=0&&dalign>=0&&(salign&3)==(dalign&3)){
  1172.         int do64,m,s;
  1173.         if((salign&7)==(dalign&7))
  1174.           {do64=1;m=8;s='q';}
  1175.         else
  1176.           {do64=0;m=4;s='l';salign&=3;}
  1177.         if(salign&7){
  1178.           fprintf(f,"\tld%c\t%s,%d(%s)\n",s,regnames[t3],-salign,regnames[t1]);
  1179.           fprintf(f,"\tld%c\t%s,%d(%s)\n",s,regnames[t4],-salign,regnames[t2]);
  1180.           cl=(1<<salign)-1;
  1181.           if(!zlleq(l2zl(m-salign),size)) cl+=((1<<(m-salign-zl2l(size)))-1)<<(salign+zl2l(size));
  1182.           fprintf(f,"\tzap\t%s,%d,%s\n",regnames[t3],cl,regnames[t3]);
  1183.           fprintf(f,"\tzapnot\t%s,%d,%s\n",regnames[t4],cl,regnames[t4]);
  1184.           fprintf(f,"\tbis\t%s,%s,%s\n",regnames[t3],regnames[t4],regnames[t3]);
  1185.           fprintf(f,"\tst%c\t%s,%d(%s)\n",s,regnames[t3],-salign,regnames[t2]);
  1186.           size=zlsub(size,zl2l(m-salign));
  1187.           salign=m-salign;
  1188.         }else
  1189.           salign=0;
  1190.         loops.val.vlong=zldiv(size,l2zl(8*m));
  1191.         if(zlleq(l2zl(2L),loops.val.vlong)){
  1192.           loops.flags=KONST;
  1193.           loops.am=0;
  1194.           load_reg(f,t3,&loops,LONG,t3);
  1195.           cl=++label;
  1196.           fprintf(f,"\t.align\t4\n%s%d:\n",labprefix,cl);
  1197.         }
  1198.         if(!zleqto(loops.val.vlong,l2zl(0))){
  1199.           for(i=0;i<8;i+=2){
  1200.             fprintf(f,"\tld%c\t%s,%d(%s)\n",s,regnames[t4],salign+i*m,regnames[t1]);
  1201.             fprintf(f,"\tld%c\t%s,%d(%s)\n",s,regnames[t5],salign+i*m+m,regnames[t1]);
  1202.             fprintf(f,"\tst%c\t%s,%d(%s)\n",s,regnames[t4],salign+i*m,regnames[t2]);
  1203.             fprintf(f,"\tst%c\t%s,%d(%s)\n",s,regnames[t5],salign+i*m+m,regnames[t2]);
  1204.           }
  1205.         }
  1206.         if(zlleq(l2zl(2L),loops.val.vlong)){
  1207.           fprintf(f,"\taddq\t%s,%d,%s\n",regnames[t1],8*m,regnames[t1]);
  1208.           fprintf(f,"\taddq\t%s,%d,%s\n",regnames[t2],8*m,regnames[t2]);
  1209.           fprintf(f,"\tsubq\t%s,1,%s\n",regnames[t3],regnames[t3]);
  1210.           fprintf(f,"\tbne\t%s,%s%d\n",regnames[t3],labprefix,cl);
  1211.         }else{
  1212.           if(!zleqto(loops.val.vlong,l2zl(0L)))
  1213.             salign+=8*m;
  1214.         }
  1215.         size=zland(size,l2zl(8*m-1));
  1216.         for(i=0;i<(zl2l(size)/m/2)*2;i+=2){
  1217.           fprintf(f,"\tld%c\t%s,%d(%s)\n",s,regnames[t4],salign+i*m,regnames[t1]);
  1218.           fprintf(f,"\tld%c\t%s,%d(%s)\n",s,regnames[t5],salign+i*m+m,regnames[t1]);
  1219.           fprintf(f,"\tst%c\t%s,%d(%s)\n",s,regnames[t4],salign+i*m,regnames[t2]);
  1220.           fprintf(f,"\tst%c\t%s,%d(%s)\n",s,regnames[t5],salign+i*m+m,regnames[t2]);
  1221.         }
  1222.         size=zland(size,l2zl(2*m-1));
  1223.         if(zl2l(size)>=m){
  1224.           fprintf(f,"\tld%c\t%s,%d(%s)\n",s,regnames[t4],salign+i*m,regnames[t1]);
  1225.           fprintf(f,"\tst%c\t%s,%d(%s)\n",s,regnames[t4],salign+i*m,regnames[t2]);
  1226.           size=zlsub(size,l2zl(m));i++;
  1227.         }
  1228.         if(zl2l(size)>0){
  1229.           if(zl2l(size)==4){
  1230.             fprintf(f,"\tldl\t%s,%d(%s)\n",regnames[t4],salign+i*m,regnames[t1]);
  1231.             fprintf(f,"\tstl\t%s,%d(%s)\n",regnames[t4],salign+i*m,regnames[t2]);
  1232.           }else{
  1233.             fprintf(f,"\tld%c\t%s,%d(%s)\n",s,regnames[t4],salign+i*m,regnames[t1]);
  1234.             fprintf(f,"\tld%c\t%s,%d(%s)\n",s,regnames[t5],salign+i*m,regnames[t2]);
  1235.             cl=(1<<zl2l(size))-1;
  1236.             fprintf(f,"\tzapnot\t%s,%d,%s\n",regnames[t4],cl,regnames[t4]);
  1237.             fprintf(f,"\tzap\t%s,%d,%s\n",regnames[t5],cl,regnames[t5]);
  1238.             fprintf(f,"\tbis\t%s,%s,%s\n",regnames[t4],regnames[t5],regnames[t4]);
  1239.             fprintf(f,"\tst%c\t%s,%d(%s)\n",s,regnames[t4],salign+i*m,regnames[t2]);
  1240.           }
  1241.         }
  1242.         p->z.flags=0; /* to prevent pr() from... */
  1243.         continue;
  1244.       }
  1245.       for(i=1;i<=32;i++){
  1246.         if(i!=17&&i!=18&&i!=19&®s[i]&®scratch[i])
  1247.           fprintf(f,"\tstq\t%s,%d(%s)\n",regnames[i],8*cl++,regnames[mr]);
  1248.       }
  1249.       if(function_calls==0) fprintf(f,"\tstq\t%s,%d(%s)\n",regnames[lr],8*cl++,regnames[mr]);
  1250.       if(cl>helps) helps=cl;
  1251.       loops.val.vlong=size;
  1252.       loops.flags=KONST;
  1253.       loops.am=0;
  1254.       load_reg(f,19,&loops,LONG,19);
  1255.       fprintf(f,"\t.global\t%smemcpy\n",idprefix);
  1256.       fprintf(f,"\tjsr\t%s,%smemcpy\n",regnames[lr],idprefix);
  1257.       fprintf(f,"\tldgp\t%s,0(%s)\n",regnames[gp],regnames[lr]);
  1258.       cl=0;
  1259.       if(ms&&mr==t3) fprintf(f,"\tlda\t%s,%s%d\n",regnames[mr],labprefix,helpl);
  1260.       if(regs[17]) fprintf(f,"\tldq\t%s,%d(%s)\n",regnames[17],8*cl++,regnames[mr]);
  1261.       if(regs[18]) fprintf(f,"\tldq\t%s,%d(%s)\n",regnames[18],8*cl++,regnames[mr]);
  1262.       if(regs[19]) fprintf(f,"\tldq\t%s,%d(%s)\n",regnames[19],8*cl++,regnames[mr]);
  1263.       for(i=1;i<=32;i++){
  1264.         if(i!=17&&i!=18&&i!=19&®s[i]&®scratch[i])
  1265.           fprintf(f,"\tldq\t%s,%d(%s)\n",regnames[i],8*cl++,regnames[mr]);
  1266.       }
  1267.       if(function_calls==0) fprintf(f,"\tldq\t%s,%d(%s)\n",regnames[lr],8*cl++,regnames[mr]);
  1268.       p->z.flags=0;
  1269.       continue;
  1270.     }
  1271.     if(isreg(q1)) wasnoreg=1; else wasnoreg=0;
  1272.     p=do_refs(f,p);
  1273.     c=p->code;
  1274.     if(c>=CONVCHAR&&c<=CONVULONG){
  1275.       int to;
  1276.       if(c==CONVCHAR) to=CHAR;
  1277.       if(c==CONVUCHAR) to=UNSIGNED|CHAR;
  1278.       if(c==CONVSHORT) to=SHORT;
  1279.       if(c==CONVUSHORT) to=UNSIGNED|SHORT;
  1280.       if(c==CONVINT) to=LONG;
  1281.       if(c==CONVUINT) to=UNSIGNED|LONG;
  1282.       if(c==CONVLONG) to=LONG;
  1283.       if(c==CONVULONG) to=UNSIGNED|LONG;
  1284.       if(c==CONVFLOAT) to=FLOAT;
  1285.       if(c==CONVDOUBLE) to=DOUBLE;
  1286.       if(c==CONVPOINTER) to=UNSIGNED|LONG;
  1287.       if((to&NQ)<=LONG&&(t&NQ)<=LONG){
  1288.         if((to&NQ)>=(t&NQ)){
  1289.           if((t&NQ)<INT){
  1290.             if(t&UNSIGNED){
  1291.               fprintf(f,"\tzapnot\t%s,%d,%s\n",regnames[q1reg],(t&NQ)==CHAR?1:3,regnames[zreg]);
  1292.               st[zreg]=EUNS;continue;
  1293.             }else{
  1294.               fprintf(f,"\tsext%c\t%s,%s\n",(t&NQ)==CHAR?'b':'w',regnames[q1reg],regnames[zreg]);
  1295.               st[zreg]=ESGN;continue;
  1296.             }
  1297.           }
  1298.           zreg=q1reg;
  1299.         }else if((t&NQ)==LONG){
  1300.           if(to&UNSIGNED)
  1301.             uextend(f,q1reg);
  1302.           else
  1303.             extend(f,q1reg);
  1304.           st[q1reg]=ESGN;
  1305.           zreg=q1reg;
  1306.         }else{
  1307.           if((to&UNSIGNED)==(t&UNSIGNED)){
  1308.             zreg=q1reg;
  1309.           }else{
  1310.             if(to&UNSIGNED){
  1311.               fprintf(f,"\tzapnot\t%s,%d,%s\n",regnames[q1reg],(t&NQ)==CHAR?1:3,regnames[zreg]);
  1312.               st[zreg]=EUNS;continue;
  1313.             }else{
  1314.               fprintf(f,"\tsext%c\t%s,%s\n",(t&NQ)==CHAR?'b':'w',regnames[q1reg],regnames[zreg]);
  1315.               st[zreg]=ESGN;continue;
  1316.             }
  1317.           }
  1318.         }
  1319.         continue;
  1320.       }
  1321.       if(to==FLOAT||to==DOUBLE){
  1322.         st[zreg]=ESGN;
  1323.         if((t&NQ)==FLOAT||(t&NQ)==DOUBLE){
  1324.           fprintf(f,"\tcvt%c%c\t%s,%s\n",x_t[to&NQ],x_t[t&NQ],regnames[q1reg],regnames[zreg]);
  1325.           continue;
  1326.         }
  1327. /*      if(t&UNSIGNED) ierror(0); */
  1328.         fprintf(f,"\tcvttqc\t%s,%s\n",regnames[q1reg],regnames[f3]);
  1329. /*      fprintf(f,"\tftoit\t%s,%s\n",regnames[q1reg],regnames[zreg]);  */
  1330. /*      fprintf(f,"\t.long\t%ld\n",(0x1cl<<26)+(0x70l<<5)+(31l<<16)+((long)(q1reg-33)<<21)+zreg-1); */
  1331.         fprintf(f,"\tstt\t%s,%ld(%s)\n",regnames[f3],framesize-addbuf,regnames[sp]);
  1332.         fprintf(f,"\tldq\t%s,%ld(%s)\n",regnames[zreg],framesize-addbuf,regnames[sp]);
  1333.         st[zreg]=ESGN;
  1334.         continue;
  1335.       }
  1336.       if((t&NQ)==FLOAT||(t&NQ)==DOUBLE){
  1337. /*      if(to&UNSIGNED) ierror(0); */
  1338. /*      fprintf(f,"\titoft\t%s,%s\n",regnames[q1reg],regnames[zreg]);  */
  1339.         fprintf(f,"\tstq\t%s,%ld(%s)\n",regnames[q1reg],framesize-addbuf,regnames[sp]);
  1340.         fprintf(f,"\tldt\t%s,%ld(%s)\n",regnames[zreg],framesize-addbuf,regnames[sp]);
  1341.         fprintf(f,"\tcvtq%c\t%s,%s\n",x_t[t&15],regnames[zreg],regnames[zreg]);
  1342.  
  1343.         continue;
  1344.       }
  1345.     }
  1346.     if(c==KOMPLEMENT){
  1347.       fprintf(f,"\tornot\t%s,%s,%s\n",regnames[r31],regnames[q1reg],regnames[zreg]);
  1348.       if((t&NQ)==INT) st[zreg]=0; else st[zreg]=ESGN;
  1349.       continue;
  1350.     }
  1351.     if(c==SETRETURN){
  1352.       if(p->z.reg){
  1353.         if(zreg==0) load_reg(f,p->z.reg,&p->q1,t,t3);
  1354.         extend(f,p->z.reg);
  1355.       }else
  1356.         ierror(0);
  1357.       continue;
  1358.     }
  1359.     if(c==GETRETURN){
  1360.       if(p->q1.reg){
  1361.         zreg=p->q1.reg;
  1362.         st[zreg]=ESGN;
  1363.       }else
  1364.         p->z.flags=0;
  1365.       continue;
  1366.     }
  1367.     if(c==CALL){
  1368.       int reg;
  1369.       if((p->q1.flags&VAR)&&p->q1.v->fi&&p->q1.v->fi->inline_asm){
  1370.         fprintf(f,"%s\n",p->q1.v->fi->inline_asm);
  1371.         pushed-=zl2l(p->q2.val.vlong);
  1372.         continue;
  1373.       }
  1374.       if((p->q1.flags&VAR)&&p->q1.v->storage_class==EXTERN&&!(g_flags[6]&USEDFLAG)){
  1375.         char *s=p->q1.v->identifier;
  1376.         if(!strcmp("abs",s)||!strcmp("labs",s)){
  1377.           fprintf(f,"\tsubq\t%s,%s,%s\n",regnames[r31],regnames[17],regnames[1]);
  1378.           fprintf(f,"\tcmovge\t%s,%s,%s\n",regnames[17],regnames[17],regnames[1]);
  1379.           continue;
  1380.         }
  1381.         if(!strcmp("fabs",s)){
  1382.           fprintf(f,"\tfabs\t%s,%s\n",regnames[17],regnames[1]);
  1383.           continue;
  1384.         }
  1385.         if(!strcmp("__va_fixargs",s)){
  1386.           fprintf(f,"\tlda\t%s,%d(%s)\n",regnames[1],fixargs,regnames[r31]);
  1387.           continue;
  1388.         }
  1389.         if(!strcmp("__va_start",s)){
  1390.           fprintf(f,"\tlda\t%s,%d(%s)\n",regnames[1],framesize-(6-fixargs)*16,regnames[sp]);
  1391.           continue;
  1392.         }
  1393.       }
  1394.       for(reg=17;reg<=22;reg++)
  1395.         extend(f,reg);
  1396.       if(q1reg){
  1397.         if(q1reg!=vp) move_reg(f,q1reg,vp);
  1398.         fprintf(f,"\tjsr\t%s,(%s),0\n",regnames[lr],regnames[vp]);
  1399.       }else{
  1400.         fprintf(f,"\tjsr\t%s,",regnames[lr]);
  1401.         probj2(f,&p->q1,t);fprintf(f,"\n");
  1402.       }
  1403.       fprintf(f,"\tldgp\t%s,0(%s)\n",regnames[gp],regnames[lr]);
  1404.       pushed-=zl2l(p->q2.val.vlong);
  1405.       continue;
  1406.     }
  1407.     if(c==ASSIGN||c==PUSH){
  1408.       if(t==0) ierror(0);
  1409.       if(q1reg){
  1410.         if(c==PUSH){
  1411.           extend(f,q1reg);
  1412.           if((t&NQ)==FLOAT){
  1413.             fprintf(f,"\tcvtst\t%s,%s\n",regnames[q1reg],regnames[f1]);
  1414.             q1reg=f1;
  1415.           }
  1416.           fprintf(f,"\tst%c\t%s,%ld(%s)\n",q1reg<=32?'q':'t',regnames[q1reg],pushed,regnames[sp]);
  1417.           pushed+=8;
  1418.           continue;
  1419.         }
  1420.         if(c==ASSIGN) zreg=q1reg;
  1421.         continue;
  1422.       }else ierror(0);
  1423.     }
  1424.     if(c==ADDRESS){
  1425.       load_address(f,zreg,&p->q1,POINTER);
  1426.       continue;
  1427.     }
  1428.     if(c==MINUS){
  1429.       if((t&NQ)<=LONG)
  1430.         fprintf(f,"\tsub%c\t%s,%s,%s\n",x_t[t&NQ],regnames[r31],regnames[q1reg],regnames[zreg]);
  1431.       else
  1432.         fprintf(f,"\tsub%c\t%s,%s,%s\n",x_t[t&NQ],regnames[f31],regnames[q1reg],regnames[zreg]);
  1433.       st[zreg]=ESGN;
  1434.       continue;
  1435.     }
  1436.     if(c==TEST){
  1437.       if(st[q1reg]==0) extend(f,q1reg);
  1438.       cmpreg=q1reg;
  1439.       cmpflag=0;
  1440.       continue;
  1441.     }
  1442.     if(c==COMPARE){
  1443.       struct IC *br=p->next;
  1444.       while(1){
  1445.         if(br->code>=BEQ&&br->code<BRA) break;
  1446.         if(br->code!=FREEREG) ierror(0);
  1447.         br=br->next;
  1448.       }
  1449.       if((t&NQ)==FLOAT||(t&NQ)==DOUBLE) cmpreg=f3; else cmpreg=t3;
  1450.       if(br->code==BEQ||br->code==BNE){
  1451.         if((t&NU)==(UNSIGNED|INT)){
  1452.           if(st[q1reg]==ESGN) extend(f,q2reg);
  1453.           else if(st[q2reg]==ESGN) extend(f,q1reg);
  1454.           else if(st[q1reg]==EUNS) uextend(f,q2reg);
  1455.           else if(st[q2reg]==EUNS) uextend(f,q1reg);
  1456.           else {extend(f,q1reg);extend(f,q2reg);}
  1457.         }
  1458.         if((t&NU)==INT){extend(f,q1reg);extend(f,q2reg);}
  1459.         if((t&NQ)==FLOAT||(t&NQ)==DOUBLE) fprintf(f,"\tsub%c\t%s,",x_t[t&NQ],regnames[q1reg]);
  1460.           else fprintf(f,"\tsub%c\t%s,",x_t[t&NQ],regnames[q1reg]);
  1461.         probj2(f,&p->q2,t);fprintf(f,",%s\n",regnames[cmpreg]);
  1462.         cmpflag=0;st[cmpreg]=ESGN;
  1463.       }else{
  1464.         char *s="";
  1465.         if(t&UNSIGNED) s="u";
  1466.         if((t&NU)==(UNSIGNED|INT)){uextend(f,q1reg);uextend(f,q2reg);}
  1467.         if((t&NU)==INT){extend(f,q1reg);extend(f,q2reg);}
  1468.         if((t&NQ)==FLOAT||(t&NQ)==DOUBLE) s="t";
  1469.         if(br->code==BLT||br->code==BGE){
  1470.           fprintf(f,"\tcmp%slt\t%s,",s,regnames[q1reg]);
  1471.           probj2(f,&p->q2,t);fprintf(f,",%s\n",regnames[cmpreg]);
  1472.           if(br->code==BGE) cmpflag=-1; else cmpflag=1;
  1473.         }else{
  1474.           fprintf(f,"\tcmp%sle\t%s,",s,regnames[q1reg]);
  1475.           probj2(f,&p->q2,t);fprintf(f,",%s\n",regnames[cmpreg]);
  1476.           if(br->code==BGT) cmpflag=-1; else cmpflag=1;
  1477.         }
  1478.       }
  1479.       continue;
  1480.     }
  1481.     if(c>=OR&&c<=AND){
  1482.       fprintf(f,"\t%s\t%s,",logicals[c-OR],regnames[q1reg]);
  1483.       probj2(f,&p->q2,t);fprintf(f,",%s\n",regnames[zreg]);
  1484.       /* hier ist mehr moeglich */
  1485.       if((t&NQ)==INT) st[zreg]=0; else st[zreg]=ESGN;
  1486.       continue;
  1487.     }
  1488.     if(c>=LSHIFT&&c<=MOD){
  1489.       int xt;
  1490.       if(c==LSHIFT&&(p->q2.flags&KONST)){
  1491.         eval_const(&p->q2.val,t);
  1492.         if(zuleqto(vulong,ul2zul(1UL))){
  1493.           fprintf(f,"\tadd%c\t%s,%s,%s\n",x_t[t&NQ],regnames[q1reg],regnames[q1reg],regnames[zreg]);
  1494.           st[zreg]=ESGN;continue;
  1495.         }
  1496.         if(zuleqto(vulong,ul2zul(2UL))){
  1497.           fprintf(f,"\ts4add%c\t%s,0,%s\n",x_t[t&NQ],regnames[q1reg],regnames[zreg]);
  1498.           st[zreg]=ESGN;continue;
  1499.         }
  1500.         if(zuleqto(vulong,ul2zul(3UL))){
  1501.           fprintf(f,"\ts8add%c\t%s,0,%s\n",x_t[t&NQ],regnames[q1reg],regnames[zreg]);
  1502.           st[zreg]=ESGN;continue;
  1503.         }
  1504.       }
  1505.       if(c==RSHIFT||c==LSHIFT){
  1506.         if(c==RSHIFT){
  1507.           if(t&UNSIGNED){
  1508.             if((t&NQ)<LONG) uextend(f,q1reg);
  1509.             fprintf(f,"\tsrl\t");
  1510.           }else{
  1511.             extend(f,q1reg);
  1512.             fprintf(f,"\tsra\t");
  1513.           }
  1514.           st[zreg]=st[q1reg];
  1515.         }else{
  1516.           fprintf(f,"\tsll\t");
  1517.           if((t&NQ)<=INT) st[zreg]=0; else st[zreg]=ESGN;
  1518.         }
  1519.         fprintf(f,"%s,",regnames[q1reg]);
  1520.         probj2(f,&p->q2,t);fprintf(f,",%s\n",regnames[zreg]);
  1521.         continue;
  1522.       }
  1523.       if((c==DIV||c==MOD)&&(t&NQ)<=LONG){
  1524.         /* Linux-Routinen aufrufen. q1=$24 q2=$25 z=$27 $28 scratch */
  1525.         if(!q1reg) ierror(0);
  1526.         if(q1reg!=25){
  1527.           if(regs[25]) fprintf(f,"\tstq\t%s,%ld(%s)\n",regnames[25],framesize-addbuf,regnames[sp]);
  1528.           move_reg(f,q1reg,25);
  1529.         }
  1530.         if(q2reg!=26&®s[26]) fprintf(f,"\tstq\t%s,%ld(%s)\n",regnames[26],framesize-addbuf+8,regnames[sp]);
  1531.         if(q2reg==25)
  1532.           fprintf(f,"\tldq\t%s,%ld(%s)\n",regnames[26],framesize-addbuf,regnames[sp]);
  1533.         else
  1534.           load_reg(f,26,&p->q2,t,26);
  1535.         if(zreg!=28&®s[28]) fprintf(f,"\tstq\t%s,%ld(%s)\n",regnames[28],framesize-addbuf+16,regnames[sp]);
  1536.         if(regs[29]) fprintf(f,"\tstq\t%s,%ld(%s)\n",regnames[29],framesize-addbuf+24,regnames[sp]);
  1537.         fprintf(f,"\t%sq%s\t%s,%s,%s\n",arithmetics[c-LSHIFT],(t&UNSIGNED)?"u":"",regnames[25],regnames[26],regnames[28]);
  1538.         if(zreg!=28) move_reg(f,28,zreg);
  1539.         if(q1reg!=25&®s[25]) fprintf(f,"\tldq\t%s,%ld(%s)\n",regnames[25],framesize-addbuf,regnames[sp]);
  1540.         if(q2reg!=26&®s[26]) fprintf(f,"\tldq\t%s,%ld(%s)\n",regnames[26],framesize-addbuf+8,regnames[sp]);
  1541.         if(zreg!=28&®s[28]) fprintf(f,"\tldq\t%s,%ld(%s)\n",regnames[28],framesize-addbuf+16,regnames[sp]);
  1542.         if(regs[29]) fprintf(f,"\tldq\t%s,%ld(%s)\n",regnames[29],framesize-addbuf+24,regnames[sp]);
  1543.         /* Was fuer st[zreg]? */
  1544.         continue;
  1545.       }
  1546.       xt=x_t[t&NQ];
  1547.       if((t&NQ)<INT) xt='l';
  1548.       fprintf(f,"\t%s%c\t%s,",arithmetics[c-LSHIFT],xt,regnames[q1reg]);
  1549.       probj2(f,&p->q2,t);fprintf(f,",%s\n",regnames[zreg]);
  1550.       st[zreg]=ESGN;
  1551.       continue;
  1552.     }
  1553.     if(c==SUBPFP){
  1554.       fprintf(f,"\tsubq\t%s,%s,%s\n",regnames[q1reg],regnames[q2reg],regnames[zreg]);
  1555.       st[zreg]=ESGN;continue;
  1556.     }
  1557.     if(c==ADDI2P||c==SUBIFP){
  1558.       if(t&UNSIGNED){
  1559.         if((t&NQ)<LONG) uextend(f,q2reg);
  1560.       }else
  1561.         extend(f,q2reg);
  1562.       if(c==ADDI2P) fprintf(f,"\taddq\t%s,",regnames[q1reg]);
  1563.       else fprintf(f,"\tsubq\t%s,",regnames[q1reg]);
  1564.       probj2(f,&p->q2,t);
  1565.       fprintf(f,",%s\n",regnames[zreg]);
  1566.       st[zreg]=ESGN;continue;
  1567.     }
  1568.     ierror(0);
  1569.   }
  1570.   function_bottom(f,v,zl2l(offset+addbuf),maxpushed);
  1571.   if(stabs) debug_exit(f,v);
  1572. }
  1573.  
  1574. int shortcut(int code,int typ)
  1575. {
  1576.   return(0);
  1577. }
  1578.  
  1579. int reg_parm(struct reg_handle *m, struct Typ *t,int vararg)
  1580. {
  1581.   int f;
  1582.   f=t->flags&NQ;
  1583.   if(f<=LONG||f==POINTER){
  1584.     if(m->nextr>=6) return(0);
  1585.     return(17+m->nextr++);
  1586.   }
  1587.   if(f==FLOAT||f==DOUBLE){
  1588.     if(m->nextr>=6) return(0);
  1589.     return(49+m->nextr++);
  1590.   }
  1591.   return(0);
  1592. }
  1593. void cleanup_cg(FILE *f)
  1594. {
  1595.   struct fpconstlist *p;
  1596.   unsigned char *ip;
  1597.   if(f&&stabs) debug_cleanup(f);
  1598.   while(p=firstfpc){
  1599.     if(f){
  1600.       int t=p->typ&NQ;
  1601.       if(section!=CODE){fprintf(f,codename);section=CODE;}
  1602.       fprintf(f,"\t.align\t3\n%s%d:\n\t",labprefix,p->label);
  1603.       if(t==FLOAT||t==DOUBLE){
  1604.         ip=(unsigned char *)&p->val.vdouble;
  1605.         fprintf(f,"\t.long\t0x%02x%02x%02x%02x",ip[3],ip[2],ip[1],ip[0]);
  1606.         if((p->typ&NQ)==DOUBLE){
  1607.           fprintf(f,",0x%02x%02x%02x%02x",ip[7],ip[6],ip[5],ip[4]);
  1608.         }
  1609.       }else{
  1610.         fprintf(f,"\t.quad\t",dct[t]);
  1611.         printval(f,&p->val,p->typ,0);
  1612.       }
  1613.       fprintf(f,"\n");
  1614.     }
  1615.     firstfpc=p->next;
  1616.     free(p);
  1617.   }
  1618.   if(f&&helps) fprintf(f,"\t.lcomm\t%s%d,%d\n",labprefix,helpl,helps*8);
  1619. }
  1620.  
  1621.  
  1622.